import { splitByBytes } from "../utils/split_by_bytes";
import { DynamicData } from "./dynamic_data";
import { IDynamicPropertyTarget } from "./idynamic_property_target";

const MAX_CHUNK_LENGTH = 32767;

//有待测试
//切勿大量进行读写，否则将会造成卡顿
export class LongDynamicJson<T> {
  private id: string;
  private target: IDynamicPropertyTarget;
  private length: DynamicData<number>;
  private data: DynamicData<string>[];
  constructor(target: IDynamicPropertyTarget, id: string, value: T = <T>undefined) {
    this.id = id;
    this.target = target;
    this.length = new DynamicData<number>(target, `${id}_length`, 0);
    this.data = [];

    const len = this.length.get();
    if (len == undefined) return;
    if (len <= 0) this.set(value);
    else {
      for (let index = 0; index < len; index++) {
        this.data[index] = new DynamicData<string>(target, this.getIdxId(index));
      }
    }
  }

  getIdxId(idx: number) {
    return `${this.id}_${idx}`;
  }

  public setRaw(value: string) {
    if (value == undefined) return;

    let lengthCounter: number = 0;
    for (let ele of splitByBytes(value, MAX_CHUNK_LENGTH)) {
      this.data[lengthCounter] = new DynamicData<string>(this.target, this.getIdxId(lengthCounter));
      this.data[lengthCounter].set(ele);
      lengthCounter++;
    }

    const previousLength = this.length.get();
    if (previousLength == undefined) return;
    const currentLength = lengthCounter;
    //清理多余部分
    if (previousLength > currentLength) {
      this.data.slice(currentLength, previousLength).forEach((ele) => {
        ele.free();
      });
      this.data = this.data.slice(0, currentLength);
    }
    this.length.set(currentLength);
  }

  public set(value: T) {
    this.setRaw(JSON.stringify(value));
  }

  public getRaw(): string {
    return this.data
      .map((ele) => {
        return ele.get();
      })
      .join("");
  }

  public get(): T {
    return JSON.parse(this.getRaw());
  }

  //获取的是分块个数而非字符长度
  public getCountOfChunks() {
    return this.length.get();
  }

  public free(): void {
    this.data.forEach((e) => {
      e.free();
    });
    this.data = [];
  }
}
